package de.slothsoft.android.authenticator;

import java.io.Serializable;

import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountManager;
import android.accounts.NetworkErrorException;
import android.content.Intent;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import de.slothsoft.android.R;
import de.slothsoft.android.authenticator.Authenticator.User;
import de.slothsoft.android.util.WebUtil;

public class LoginActivity extends AccountAuthenticatorActivity {

    public static final String ARG_LOGIN_OPTIONS = "LOGIN_OPTIONS"; //$NON-NLS-1$
    public static final String ARG_APPLICATION = "ARG_APPLICATION"; //$NON-NLS-1$

    public static final String SIGN_UP_ACTIVITY = "http://slothsoft.de/user/register"; //$NON-NLS-1$

    private static final int REQUEST_SIGNUP = 1;

    private LoginOptions loginOptions;
    private TextView userId;
    private TextView userPassword;

    @Override
    public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_login);

	this.loginOptions = (LoginOptions) getIntent().getSerializableExtra(ARG_LOGIN_OPTIONS);
	this.userId = (TextView) findViewById(R.id.login_id);
	this.userPassword = (TextView) findViewById(R.id.login_password);

	styleForApplication(getIntent().getStringExtra(ARG_APPLICATION));

	updateControls();
	hookListeners();
    }

    private void styleForApplication(String id) {
	if ("wasbinich".equals(id)) { //$NON-NLS-1$
	    BitmapDrawable drawable = (BitmapDrawable) getResources().getDrawable(R.drawable.background_wbi);
	    drawable.setTileModeX(TileMode.REPEAT);
	    findViewById(R.id.layout).setBackgroundDrawable(drawable);
	}
    }

    private void updateControls() {
	if (this.loginOptions.userName != null) {
	    this.userId.setText(this.loginOptions.userName);
	}
    }

    private void hookListeners() {
	findViewById(R.id.login_submit).setOnClickListener(new View.OnClickListener() {
	    @Override
	    public void onClick(View v) {
		submit();
	    }
	});
	findViewById(R.id.login_register).setOnClickListener(new View.OnClickListener() {
	    @Override
	    public void onClick(View v) {
		// Intent signup = new Intent(getBaseContext(),
		// AccountAuthenticatorUtil.findClass(
		// getIntent().getExtras(), ARG_SIGN_UP_ACTIVITY,
		// RegisterActivity.class));
		// signup.putExtras(getIntent().getExtras());
		// startActivityForResult(signup, REQUEST_SIGNUP);
		WebUtil.openUrl(LoginActivity.this, SIGN_UP_ACTIVITY);
	    }
	});
    }

    public void submit() {
	new AsyncTask<String, Void, Intent>() {

	    @Override
	    protected Intent doInBackground(String... params) {
		final Intent res = new Intent();
		res.putExtras(performLogin());
		return res;
	    }

	    @Override
	    protected void onPostExecute(Intent intent) {
		if (intent.hasExtra(AccountManager.KEY_ERROR_MESSAGE)) {
		    showMessage(intent.getStringExtra(AccountManager.KEY_ERROR_MESSAGE));
		} else {
		    finishLogin(intent);
		}
	    }
	}.execute();
    }

    protected Bundle performLogin() {
	Log.d("slothsoft", "performLogin()"); //$NON-NLS-1$ //$NON-NLS-2$
	Bundle data = new Bundle();
	try {
	    User user = new User(this.userId.getText().toString(), this.userPassword.getText().toString());
	    if (this.loginOptions.oAuth2Authenticator.areCorrectCredentials(user)) {
		data.putString(AccountManager.KEY_ACCOUNT_NAME, user.id);
		data.putString(AccountManager.KEY_PASSWORD, user.password);
		data.putString(AccountManager.KEY_AUTHTOKEN, AccountAuthenticator.DUMMY_TOKEN);
	    } else {
		data.putString(AccountManager.KEY_ERROR_MESSAGE, "Invalid credentials");
	    }
	} catch (NetworkErrorException e) {
	    data.putString(AccountManager.KEY_ERROR_MESSAGE, e.getMessage());
	}
	return data;
    }

    protected void finishLogin(Intent intent) {
	String userId = intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
	String userPassword = intent.getStringExtra(AccountManager.KEY_PASSWORD);
	String token = intent.getStringExtra(AccountManager.KEY_AUTHTOKEN);

	AccountManager manager = AccountManager.get(getBaseContext());
	Account account = new Account(userId, this.loginOptions.accountType);

	if (!manager.addAccountExplicitly(account, token, null)) {
	    // account already existed
	    manager.setAuthToken(account, this.loginOptions.authTokenType, token);
	}
	manager.setPassword(account, userPassword);

	setAccountAuthenticatorResult(intent.getExtras());
	setResult(RESULT_OK, intent);
	finish();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	if (requestCode == REQUEST_SIGNUP && resultCode == RESULT_OK) {
	    finishLogin(data);
	} else {
	    super.onActivityResult(requestCode, resultCode, data);
	}
    }

    @Override
    public void onBackPressed() {
	setResult(RESULT_CANCELED);
	super.onBackPressed();
    }

    protected void showMessage(String message) {
	Toast toast = Toast.makeText(getBaseContext(), message, Toast.LENGTH_SHORT);
	toast.show();
    }

    /*
     *
     */

    public static class LoginOptions implements Serializable {

	private static final long serialVersionUID = -6501656324484448836L;

	public String accountType;
	public String userName;
	public String authTokenType;
	public Authenticator oAuth2Authenticator;
	public boolean newAccount;

	public LoginOptions(String accountType, String userName, String authTokenType,
		Authenticator oAuth2Authenticator, boolean newAccount) {
	    this.accountType = accountType;
	    this.userName = userName;
	    this.authTokenType = authTokenType;
	    this.oAuth2Authenticator = oAuth2Authenticator;
	    this.newAccount = newAccount;
	}
    }

}
